home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / zcrypt10.zip / CRYPT.C next >
C/C++ Source or Header  |  1991-11-08  |  8KB  |  265 lines

  1. /*
  2.    This code is not copyrighted and is put in the public domain. It
  3.    was originally written in Europe and can be freely distributed from
  4.    any country except the U.S.A. If this code is imported in the U.S.A,
  5.    it cannot be re-exported from the U.S.A to another country. (This
  6.    restriction might seem curious but this is what US law requires.)
  7.  */
  8.  
  9. /* This encryption code is a direct transcription of the algorithm from
  10.    Roger Schlafly, described by Phil Katz in the file appnote.txt. This
  11.    file is distributed with the PKZIP program (even in the version without
  12.    encryption capabilities).
  13.  */
  14.  
  15. #include "zip.h"
  16. #include <time.h>
  17.  
  18. #if !defined (MODERN)
  19.    void srand OF((unsigned int));
  20.    int rand OF((void));
  21. #endif
  22.  
  23. local int decrypt_byte OF((void));
  24. local void update_keys OF((int c));
  25. local void init_keys OF((char *passwd));
  26.       int zencode OF((int c));
  27. local int zdecode OF((int c));
  28.  
  29. local ulg keys[3]; /* keys defining the pseudo random sequence */
  30.  
  31. /***********************************************************************
  32.  * Return the next byte in the pseudo-random sequence
  33.  */
  34. local int decrypt_byte()
  35. {
  36.    ush temp;
  37.  
  38.    temp = (ush)keys[2] | 2;
  39.    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
  40. }
  41.  
  42. /***********************************************************************
  43.  * Update the encryption keys with the next byte of plain text
  44.  */
  45. local void update_keys(c)
  46.     int c;                  /* byte of plain text */
  47. {
  48.     keys[0] = crc32(keys[0], c);
  49.     keys[1] += keys[0] & 0xff;
  50.     keys[1] = keys[1] * 134775813L + 1;
  51.     keys[2] = crc32(keys[2], (int)(keys[1] >> 24));
  52. }
  53.  
  54.  
  55. /***********************************************************************
  56.  * Initialize the encryption keys and the random header according to
  57.  * the given password.
  58.  */
  59. local void init_keys(passwd)
  60.     char *passwd;             /* password string to modify keys with */
  61. {
  62.     keys[0] = 305419896L;
  63.     keys[1] = 591751049L;
  64.     keys[2] = 878082192L;
  65.     while (*passwd != '\0') {
  66.         update_keys((int)*passwd);
  67.         passwd++;
  68.     }
  69. }
  70.  
  71. /***********************************************************************
  72.  * Return the encoded value of the byte c of the plain text
  73.  */
  74. local int zencode(c)
  75.     int c;
  76. {
  77.     int temp = decrypt_byte();
  78.  
  79.     update_keys(c);
  80.     return temp ^ c;
  81. }
  82.  
  83. /***********************************************************************
  84.  * Return the decoded value of the byte c of the cypher text
  85.  */
  86. local int zdecode(c)
  87.     int c;
  88. {
  89.     int temp = c ^ decrypt_byte();
  90.  
  91.     update_keys(temp);
  92.     return temp;
  93. }
  94.  
  95.  
  96. /***********************************************************************
  97.  * Write encryption header to file zfile using the password passwd
  98.  * and the cyclic redundancy check crc
  99.  */
  100. void crypthead(passwd, crc, zfile)
  101.     char *passwd;             /* password string */
  102.     ulg crc;                  /* crc of file being encrypted */
  103.     FILE *zfile;              /* where to write header to */
  104. {
  105.     int n = 10;               /* size of random header */
  106.  
  107.     init_keys(passwd);
  108.  
  109.     /* Encrypt random header (last two bytes is high word of crc) */
  110.  
  111.     srand((unsigned int)time(NULL));      /* initialize generator */
  112.     while (n--) {
  113.         putc(zencode(rand() >> 7), zfile);
  114.     }
  115.     putc(zencode(crc >> 16), zfile);
  116.     putc(zencode(crc >> 24), zfile);
  117. }
  118.  
  119.  
  120. #ifdef UTIL
  121.  
  122. /***********************************************************************
  123.  * Encrypt the zip entry described by z from file source to file dest
  124.  * using the password passwd.  Return an error code in the ZE_ class.
  125.  */
  126. int zipcloak(z, source, dest, passwd)
  127.     struct zlist far *z;    /* zip entry to encrypt */
  128.     FILE *source, *dest;    /* source and destination files */
  129.     char *passwd;           /* password string */
  130. {
  131.     int c;                  /* input byte */
  132.     int res;                /* result code */
  133.     ulg n;                  /* holds offset and counts size */
  134.  
  135.     /* Set encrypted bit and write local header to output file */
  136.     if ((n = ftell(dest)) == -1L) return ZE_TEMP;
  137.     z->off = n;
  138.     z->flg |= 1;
  139.     z->lflg |= 1;
  140.     z->siz += 12;
  141.     if ((res = putlocal(z, dest)) != ZE_OK) return res;
  142.  
  143.     /* Initialize keys with password and write random header */
  144.     crypthead(passwd, z->crc, dest);
  145.  
  146.     /* Skip local header in input file */
  147.     if (fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
  148.               SEEK_CUR)) {
  149.         return ferror(source) ? ZE_READ : ZE_EOF;
  150.     }
  151.  
  152.     /* Encrypt data */
  153.     for (n = z->siz - 12; n; n--) {
  154.         if ((c = getc(source)) == EOF) {
  155.             return ferror(source) ? ZE_READ : ZE_EOF;
  156.         }
  157.         putc(zencode(c), dest);
  158.     }
  159.     if (fflush(dest) == EOF) return ZE_TEMP;
  160.     return ZE_OK;
  161. }
  162.  
  163. /***********************************************************************
  164.  * Decrypt the zip entry described by z from file source to file dest
  165.  * using the password passwd.  Return an error code in the ZE_ class.
  166.  */
  167. int zipbare(z, source, dest, passwd)
  168.     struct zlist far *z;  /* zip entry to encrypt */
  169.     FILE *source, *dest;  /* source and destination files */
  170.     char *passwd;         /* password string */
  171. {
  172.     int c0, c1;           /* last two input bytes */
  173.     ulg offset;           /* used for file offsets */
  174.     ulg size;             /* size of input data */
  175.     int r;                /* size of encryption header */
  176.     int res;              /* return code */
  177.  
  178.     /* Save position and skip local header in input file */
  179.     if ((offset = ftell(source)) == -1L ||
  180.         fseek(source, (long)(4 + LOCHEAD + (ulg)z->nam + (ulg)z->ext),
  181.               SEEK_CUR)) {
  182.         return ferror(source) ? ZE_READ : ZE_EOF;
  183.     }
  184.     /* Initialize keys with password */
  185.     init_keys(passwd);
  186.  
  187.     /* Decrypt encryption header, save last two bytes */
  188.     c1 = 0;
  189.     for (r = 12; r; r--) {
  190.         c0 = c1;
  191.         if ((c1 = zdecode(getc(source))) == EOF) {
  192.             return ferror(source) ? ZE_READ : ZE_EOF;
  193.         }
  194.     }
  195.  
  196.     /* If last two bytes of header don't match crc, back up and just copy */
  197.     if ((ush)(c0 | (c1<<8)) != (ush)(z->crc >> 16)) {
  198.         if (fseek(source, offset, SEEK_SET)) {
  199.             return ferror(source) ? ZE_READ : ZE_EOF;
  200.         }
  201.         if ((res = zipcopy(z, source, dest)) != ZE_OK) return res;
  202.         return ZE_MISS;
  203.     }
  204.  
  205.     /* Clear encrypted bit and write local header to output file */
  206.     if ((offset = ftell(dest)) == -1L) return ZE_TEMP;
  207.     z->off = offset;
  208.     z->flg &= ~1;
  209.     z->lflg &= ~1;
  210.     z->siz -= 12;
  211.     if ((res = putlocal(z, dest)) != ZE_OK) return res;
  212.  
  213.     /* Decrypt data */
  214.     for (size = z->siz; size; size--) {
  215.         if ((c1 = getc(source)) == EOF) {
  216.             return ferror(source) ? ZE_READ : ZE_EOF;
  217.         }
  218.         putc(zdecode(c1), dest);
  219.     }
  220.     if (fflush(dest) == EOF) return ZE_TEMP;
  221.  
  222.     return ZE_OK;
  223. }
  224.  
  225.  
  226. #else /* !UTIL */
  227.  
  228. /***********************************************************************
  229.  * If requested, encrypt the data in buf, and in any case call fwrite()
  230.  * with the arguments to zfwrite().  Return what fwrite() returns.
  231.  */
  232. int zfwrite(buf, item_size, nb, f)
  233.     voidp *buf;               /* data buffer */
  234.     extent item_size;         /* size of each item in bytes */
  235.     extent nb;                /* number of items */
  236.     FILE *f;                  /* file to write to */
  237. {
  238.     if (key != NULL) {        /* key is the global password pointer */
  239.         ulg size;             /* buffer size */
  240.         char *p = (char*)buf; /* steps through buffer */
  241.  
  242.         /* Encrypt data in buffer */
  243.         for (size = item_size*(ulg)nb; size != 0; p++, size--) {
  244.             *p = (char)zencode(*p);
  245.         }
  246.     }
  247.  
  248.     /* Write the buffer out */
  249.     return fwrite(buf, item_size, nb, f);
  250. }
  251.  
  252. /***********************************************************************
  253.  * Encrypt the byte c and then do a putc().  The macro zputc defined in
  254.  * crypt.h checks keys and calls zfputc if needed.  Return what putc()
  255.  * returns.
  256.  */
  257. int zfputc(c, f)
  258.     int c;                  /* character to write */
  259.     FILE *f;                /* file to write it to */
  260. {
  261.     return putc(zencode(c), f);
  262. }
  263.  
  264. #endif /* ?UTIL */
  265.